#include "thermalcam.h"

Json::Value thermalCamera_tempInfoBeatInit(const std::string id);
std::string thermalCamera_tempInfoBeatInit(const string id, const float max, const float min, const float ave, const int pos, const string time);

//real temp info and send img
void CALLBACK GetThermInfoCallback_v2(DWORD dwType, void* lpBuffer, DWORD dwBufLen, void* pUserData) ;
	static int SendTempImgInterval = 1;
	static int SendTempImgcond = 0;
	static bool B_sendRealTempImg = false;
void CALLBACK GetThermInfoCallback(DWORD dwType, void* lpBuffer, DWORD dwBufLen, void* pUserData) ;
//only real temp info
void CALLBACK GetThermInfoCallback_v3(DWORD dwType, void* lpBuffer, DWORD dwBufLen, void* pUserData);

void writeFileIntoLocal(char *pfile, const unsigned int len, const string path);
void deleteFile(const string filePath);
std::string getImageName(const std::string imgType);

ClientToService *CLIENTTOSERVICE = NULL;

string IP_service;
int PORT_service;

std::mutex mutexTempInfo;
	float max_thermalTemp = 0;
	float min_thermalTemp = 0;
	float avg_thermalTemp = 0;
	float diff_thermalTemp = 0;

	bool isCapPicture = false;
	string thermalImagePath_ftp = "null";

std::mutex mutexTempAlarm;
     bool isTempAlarm;
 	 string TempAlarmImagePath = "null";
	float highPositionFx = 0;
	float highPositionFy = 0;
	 //Mat alarmImage;


 mutex mutexExitClient;
     bool bExitClient;

thermal::thermal(const string iniPath):
				m_selfName("null"),
				m_serviceIp("192.168.1.1"),
				m_servicePort(12345),
                mhckLibDir(HCK_LIB_DIR),
				m_fAlarmVal(80),
				m_fAlertVal(40),
				m_iniFilePath(iniPath),
				m_rule(0),
				m_realtemp_interval(3),
				mb_alarmDetect(true),
				mb_realTempDetect(true),
				mb_sendRealTempImg(true),	
				m_sendImgInterval(0),
				m_setThermalSysParams(false)
{
	
	string exePath;
	thermal_get_exe_path(exePath, 2);

	ruitu::IniFile ini(m_iniFilePath.c_str());

	unsigned int dwSize = 0;
	char sSection[16] = "THERMAL";

	//get robotselt name
	m_selfName = ini.readstring(sSection, "RobotName", "error", dwSize);
	//get robot name 
	strncpy((char*)m_channelName, m_selfName.c_str(), m_selfName.length() + 1);
	//<<<
	
	//camera device param 
	mIP = ini.readstring(sSection, "DeviceAddress", "error", dwSize);
	mPort = ini.readinteger(sSection, "DevicePort", 0);
	mUserName = ini.readstring(sSection, "UserName", "error", dwSize); 
	mPassword = ini.readstring(sSection, "Password", "error", dwSize);
	dwChannel = ini.readinteger(sSection, "Channel", 0);
	m_rule = ini.readinteger(sSection, "Rule", 0);
	//<<<

	m_sendImgInterval = ini.readinteger(sSection, "SendThermalInfoImgInterval", 1);
	SendTempImgInterval = m_sendImgInterval;

	mb_sendRealTempImg = ini.readbool(sSection, "IsSendThermalInfoImg");
	B_sendRealTempImg = mb_sendRealTempImg;


	
	alarmPath_service = ini.readstring(sSection, "alarmPath_service", "error", dwSize);
	ftpTempPath_thermal_service = ini.readstring(sSection, "ftpTempPath_thermal_service", "error", dwSize);

	mhckLibDir = exePath+"lib/";           // ini.readstring(sSection, "HCK_LIB_DIR", "error", dwSize);
	alarmPath_local = exePath+"tempPictures";   //ini.readstring(sSection, "alarmPath_local", "error", dwSize);
	if(access(alarmPath_local.c_str(),  F_OK) != 0){
			string commandMkdir = "";
			if (1){
				commandMkdir = "mkdir -m 777 -p " + alarmPath_local;
			}
			// else{
			// 	commandMkdir = "echo "+password+" | sudo -S mkdir -m 777 -p " + alarmPath_local;
			// }
			
			const int sysres = system(commandMkdir.c_str());
			if (sysres != 0){
				WARNING("sysres=%d\n", sysres);
			}
			if(access(alarmPath_local.c_str(),  F_OK) != 0){
				printf("alarmPath_local don't exist !!!\n");
				exit(-1);
			}
	}

	m_serviceIp = ini.readstring(sSection, "ConnectLinux_ip", "error", dwSize);
	m_servicePort = ini.readinteger(sSection, "ConnectLinux_port", 0);

	m_setThermalSysParams = ini.readbool(sSection, "SetThermalSysParams");
	PRINTINFO("m_setThermalSysParams = %d\n", m_setThermalSysParams);

	IP_service = m_serviceIp;
	PORT_service = m_servicePort;



	if(mIP == "error" || mPort == 0 || mhckLibDir == "error"){
		printf("ini file load error\n");
		throw "thermal() failed";
	}

	m_bEnbaleThermometry = FALSE;
	m_bStreamOverlay = FALSE;
	m_bPictureOverlay = FALSE;
	m_bySensitivity = 0;

    m_comTemperatureColor = 1;
    m_iHighTemperature = 0;     //high valude   -273~10000
    m_iLowTemperature = 0;      //low value     -273~10000
    m_comDistanceUnit = 2;           // 距离单位: 0- 米(m)，1- 英尺(feet)，2-厘米（cm）  
    m_cmbFireImageModea = 0;
    m_cmbThermometryCurve = 0;
    m_fThernomertryEmissivity = 0.96;      //发射率(发射率 精确到小数点后两位)[0.01, 1.00](即：物体向外辐射能量的本领)
    m_byEnviroHumidity = 0;
    m_iEnviroTemperature = 0;
    m_iCorrectionVolume = 0;
    m_bChkCenterSpecialPoint = FALSE;
    m_bChkHighestSpecialPoint = FALSE;
    m_bChkLowestSpecialPoint = FALSE;
    m_bChkReflectiveEnabled = FALSE;
    m_dwDistanceMeter = 3;
    m_fReflectiveTemp = 0.0f;
    m_bShowTempStripEnable = FALSE;
    m_fAlarmVal = ini.readinteger(sSection, "Tempalarm", 0);                             //报警温度阈值，-100.0-1000.0度（精确到小数点后一位)
    m_fAlertVal = ini.readinteger(sSection, "Tempalert", 0);                             //预警温度阈值，-100.0-1000.0度（精确到小数点后一位）
    float   m_ThermalOpticalTransmittance = 1.0;  
    float   m_externalOpticsWindowCorrection = 20;   
    BOOL    m_displayMaxTemperatureEnabled = 1;             // 显示最高温 0-不显示 1-显示
    BOOL    m_displayMinTemperatureEnabled = 1;             // 显示最低温 0-不显示 1-显示
    BOOL    m_displayAverageTemperatureEnabled = 0;         // 显示平均温 0-不显示 1-显示
    BYTE    m_thermometryInfoDisplayposition    = 1;        // 测温信息显示位置 0-保留 1-跟随规则 2-屏幕左上角
    int		m_AlertFilteringTime = 0;
    int     m_AlarmFilteringTime = 0;
    BYTE    m_displayTemperatureInOpticalChannelEnabled = 0;
    BOOL    m_displayCentreTemperatureEnabled = FALSE;

	printf("alarmImage folder:%s \n", alarmPath_service.c_str());

	CLIENTTOSERVICE = new ClientToService(m_selfName, m_serviceIp, m_servicePort, -1, 50000, "thermal");
	if(CLIENTTOSERVICE == NULL){
		delete CLIENTTOSERVICE;
		CLIENTTOSERVICE = NULL;
		throw "clientToService new() error";
	}
	//mt_clientToService = thread(&ClientToService::m_working, CLIENTTOSERVICE, 10);
	//sleep(1);

}
thermal::~thermal(){
	printf("~thermal()\n");
	closeHikSDK();
	PRINTINFO("hiksdk exited\n");

	CLIENTTOSERVICE->m_setExit(true);
	if(mt_clientToService.joinable()){
		PRINTINFO("clientToService: m_working() exiting\n");
		mt_clientToService.join();
	}
	delete CLIENTTOSERVICE;
	CLIENTTOSERVICE = NULL;

	
	PRINTINFO("~thermal() exited\n");
}
int thermal::initHikSDK()
{

    //device init
    NET_DVR_Init();
    SDK_Version();
	//NET_DVR_SetLogToFile(3, "./sdkLog");

	printf("  \n");

	//如果调试过程碰到104预览组件加载失败错误，就需要在主程序中用NET_DVR_SetSDKInitCfg函数进行重新连接
	NET_DVR_LOCAL_SDK_PATH struComPath = {0};
	strcpy(struComPath.sPath, mhckLibDir.c_str());
	int res = NET_DVR_SetSDKInitCfg(NET_SDK_INIT_CFG_SDK_PATH, &struComPath);		//success on 1, false on 0
	printf("HCNetSDKCom path load success! sPath: %s -- %d\n",mhckLibDir.c_str(), res );

    //set connect and reconnect time
    NET_DVR_SetConnectTime(2000,1);    //waitTime, reconnect times
    NET_DVR_SetReconnect(10000, true);

    //register device
    //user login info
    NET_DVR_USER_LOGIN_INFO struLoginInfo = {0};
    struLoginInfo.bUseAsynLogin = false;

	PRINTINFO("cameraIp: %s\n\tcameraPort: %d\n\tuserName: %s\n\tpassWord: %s\n", mIP.c_str(), mPort, mUserName.c_str(),mPassword.c_str() );
    struLoginInfo.wPort = mPort;
    strcpy(struLoginInfo.sDeviceAddress, mIP.c_str());
    strcpy(struLoginInfo.sUserName, mUserName.c_str());
    strcpy(struLoginInfo.sPassword, mPassword.c_str());

	// struLoginInfo.wPort = 8000;
    // strcpy(struLoginInfo.sDeviceAddress, "192.168.1.63");
    // strcpy(struLoginInfo.sUserName, "admin");
    // strcpy(struLoginInfo.sPassword, "abcd1234");

    //device info, output params
    //
    LUserID = NET_DVR_Login_V40(&struLoginInfo, &struDeviceInfoV40);
    if (LUserID < 0)
    {
        printf("pyd1---Login error, error code: %d\n", NET_DVR_GetLastError());
        NET_DVR_Cleanup();
        return -1;
    }
    dwChannel = struDeviceInfoV40.struDeviceV30.byStartChan;

    //analog channels
    int analogChannels = struDeviceInfoV40.struDeviceV30.byChanNum;
    //ip channels
    int ipChannels = struDeviceInfoV40.struDeviceV30.byIPChanNum + struDeviceInfoV40.struDeviceV30.byHighDChanNum * 256;
    cout << "the max number of analog channels: " << analogChannels << endl;
    cout << "the max number of ip channels: " << ipChannels << endl;

  	int iRet;
	// //get 测温Mode配置
	if(getThermMode(LUserID) == -1){
		const int ttt = 0;
	//debug
		//return -1;
	}

	//get 测温基本参数配置
	if(m_setThermalSysParams && setThermParams(LUserID) == -1){
		return -1;
	}
	return 0;

#if 0
	// //get realtime params
	// NET_DVR_STD_CONFIG struStdConfig2 = { 0 };
	// NET_DVR_REALTIME_THERMOMETRY_COND struThermCond = { 0 };
	// struStdConfig2.lpCondBuffer = &dwChannel;
	// struStdConfig2.dwCondSize = sizeof(dwChannel);
	// struStdConfig2.lpInBuffer = NULL;
	// struStdConfig2.dwInSize = 0;
	
	// struStdConfig2.lpOutBuffer = &struThermCond;   //out param
	// struStdConfig2.dwOutSize = sizeof(struThermCond);

	// memset(m_szStatusBuf, 0, ISAPI_STATUS_LEN);
	// struStdConfig2.lpStatusBuffer = m_szStatusBuf;      //out param
	// struStdConfig2.dwStatusSize = ISAPI_STATUS_LEN;
	// //get TemplateModes
	// iRet = NET_DVR_GetSTDConfig(LUserID, NET_DVR_GET_REALTIME_THERMOMETRY, &struStdConfig2);
	// if (!iRet)	
	// {
	// 	printf("NET_DVR_GET_REALTIME_THERMOMETRY failed, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
    //     return -1;
	// }
	// else
	// {
	// 	printf("NET_DVR_GET_REALTIME_THERMOMETRY success! iRet: %d\n", iRet);
	// 	printf ("NET_DVR_GET_REALTIME_THERMOMETRY:  %d\n", struThermCond.byMode);	//0 : normal
		
#endif

    
}
int thermal::mhckRun_ftp()
{
    int res = initHikSDK();	//初始化sdk
	if (res == -1){
		printf("mhckRun error\n");
		return -1;
	}
	Demo_GetDeviceState(LUserID);
	if(getAbility_thermal(LUserID) == -1){
		return -1;
	}

	if(mb_alarmDetect && AlarmDetect(LUserID) == -1)		//报警功能检测
	{
		return -1;
	}

	if(mb_realTempDetect && RealTempDetect(LUserID) == -1)		//realDetect 检测
	{
		return -1;
	}

	// if(RealTempDetect_v2(LUserID) == -1)		//realDetect 检测
	// {
	// 	return -1;
	// }
	printf("********************\n");
	return 0;
}

int thermal::mhckRun_tcp()
{
    int res = initHikSDK();	//初始化sdk
	if (res == -1){
		printf("mhckRun error\n");
		return -1;
	}
	Demo_GetDeviceState(LUserID);
	if(getAbility_thermal(LUserID) == -1){
		return -1;
	}

	if(mb_alarmDetect && AlarmDetect_v2(LUserID) == -1)		//报警功能检测
	{
		return -1;
	}

	if(mb_realTempDetect && RealTempDetect_v2(LUserID) == -1)		//realDetect 检测
	{
		return -1;
	}
	printf("********************\n");
	return 0;
}

void thermal::closeHikSDK()
{
	// //关闭长连接配置接口所创建的句柄，释放资源  LHandle_alarm
	if ( closeRealTempDetect(mLHandle_realtemp) == 0){
		printf("撤销 realDetect 通道 success\n");
	}
	else{
		printf("撤销 realDetect 通道 failed\n");
	}

	//撤销布防上传通道
	if ( closeAlarmDetect(mLHandle_alarm) == 0){
		printf("撤销布防上传通道 success\n");
	}
	else{
		printf("撤销布防上传通道 failed\n");
	}
	
  	//注销用户
	NET_DVR_Logout(LUserID);
	//释放SDK资源
	NET_DVR_Cleanup();
	printf("Thermal camera closed! Time: %ld\n", time(NULL)); //和初始化时秒数相减，可以查看运行秒数
}
#if 1
/*
NET_DVR_THERMOMETRY_ALARM
Members:
	dwSize  结构体大小  
	dwChannel  通道号  
	byRuleID  规则ID  
	byThermometryUnit  测温单位: 0- 摄氏度（℃），1- 华氏度（℉），2- 开尔文(K)  wPresetNo  预置点号  
	NET_PTZ_INFO struPtzInfo  PTZ坐标信息  
	byAlarmLevel  报警等级：0- 预警，1- 报警  
	byAlarmType  报警类型：0- 最高温度，1- 最低温度，2- 平均温度  
	byAlarmRule  报警规则：0- 大于，1- 小于  
	byRuleCalibType  规则标定类型：0- 点，1- 框，2- 线 

	NET_VCA_POINT struPoint  点测温坐标（当规则标定类型为点的时候生效）  
	NET_VCA_P0LYGON struRegion  区域测温坐标（当规则标定类型为框或线的时候生效） 

	fRuleTemperature  配置规则温度，精确到小数点后一位，取值范围：-40~1000  
	fCurrTemperature  当前温度，精确到小数点后一位，取值范围：-40~1000  
	dwPicLen  可见光图片长度  
	dwThermalPicLen  热成像图片长度  
	dwThermalInfoLen  热成像附加信息长度  

	char *pPicBuff  可见光图片指针，存放可见光图片数据，JPEG格式  
	char *pThermalPicBuff  热成像图片指针，存放热成像图片数据，JPEG格式  
	char *pThermalInfoBuff  热成像附加信息指针，存放热成像信息  
	NET_VCA_POINT struHighestPoint  线、框测温最高温度位置坐标（当规则标定类型为线、框的时候生效）  

	fToleranceTemperature  容差温度,精确到小数点后一位(-40-1000),（浮点数+100）  
	dwAlertFilteringTime  温度预警等待时间，单位：秒，范围为0-200秒，默认为0秒  
	dwAlarmFilteringTime  温度报警等待时间，单位：秒，范围为0-200秒，默认为0秒  
	dwAlertFilteringTime  温度突变记录周期，单位：秒  
	dwAlarmFilteringTime  温度突变值,精确到小数点后一位(大于0)  
	byPicTransType  图片数据传输方式：0-二进制，1-URL  
	byRes  保留字节 
*/

//save img in local
BOOL CALLBACK MessageCallback3(LONG lCommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen, void* pUser) 
{
	// NET_DVR_JPEGPARA strPicPara = {0};
	// strPicPara.wPicQuality = 0;	//图片质量系数：0-最好，1-较好，2-一般 
	// strPicPara.wPicSize = 500;	//500-384*288
	//printf("debug:  thermalcam.cpp::  MessageCallback3()\n");
	switch(lCommand)      
	{                
		case COMM_THERMOMETRY_ALARM: //温度预警或者温度报警         
		{
			//printf("温度预警或者温度报警 : \n");    
			NET_DVR_THERMOMETRY_ALARM struThermometryAlarm = {0};             
			memcpy(&struThermometryAlarm, pAlarmInfo, sizeof(NET_DVR_THERMOMETRY_ALARM));             
			if (0 == struThermometryAlarm.byRuleCalibType)             
			{                 
				printf("点测温: \n"); 
			}             
			else if (1 == struThermometryAlarm.byRuleCalibType || 2 == struThermometryAlarm.byRuleCalibType)             
			{
				//printf("线测温或者框测温: \n");
				const string imgName = getImageName(".jpg");  
                const string filePathName = alarmPath_local + "/" + imgName;	//save local
				FILE *fsnapPic = NULL;
				fsnapPic = fopen(const_cast<char*>(filePathName.c_str()), "wb");
				fwrite(struThermometryAlarm.pThermalPicBuff, struThermometryAlarm.dwThermalPicLen, 1, fsnapPic);
				fclose(fsnapPic);
				
				const string currentDate = getcurrentDate();
				sendftp(IP_service, filePathName, alarmPath_service+"/"+currentDate, "robot001", "robot001", "./thermal_alarm.sh");

				const string alarmImageNamePathToService = alarmPath_service + "/" + currentDate +  "/" + imgName;
				pushAlarm(alarmImageNamePathToService, "imgStr", struThermometryAlarm.struHighestPoint.fX, struThermometryAlarm.struHighestPoint.fY);					//add alarm info to client
				//cout << "thermalcam.cpp ::MessageCallback3() " << alarmImageNamePathToService << endl;
				
			}
			break;         
		} //case            
		case COMM_THERMOMETRY_DIFF_ALARM: //温差报警         
		{
			printf("温差报警 : \n");    
			NET_DVR_THERMOMETRY_DIFF_ALARM struThermometryDiffAlarm = {0};             
			memcpy(&struThermometryDiffAlarm, pAlarmInfo, sizeof(NET_DVR_THERMOMETRY_DIFF_ALARM));  
          
			if (0 == struThermometryDiffAlarm.byRuleCalibType)             
			{
				printf("点测温: \n");   
				      
			}             
			else if (1 == struThermometryDiffAlarm.byRuleCalibType || 2 == struThermometryDiffAlarm.byRuleCalibType)             
			{
				printf("线测温或者框测温 : \n");          
				int i = 0;                 
				int iPointNum = struThermometryDiffAlarm.struRegion[0].dwPointNum;                 
				for (i = 0; i < iPointNum; i++)                 
				{                     
					float fX = struThermometryDiffAlarm.struRegion[0].struPos[i].fX;                     
					float fY = struThermometryDiffAlarm.struRegion[0].struPos[i].fY;                     
					printf("测温区域1坐标点: X%d:%f,Y%d:%f;\n", iPointNum + 1, fX, iPointNum + 1, fY);                 
				}                 
				iPointNum = struThermometryDiffAlarm.struRegion[1].dwPointNum;                 
				for (i = 0; i < iPointNum; i++)                 
				{                     
					float fX = struThermometryDiffAlarm.struRegion[1].struPos[i].fX;                     
					float fY = struThermometryDiffAlarm.struRegion[1].struPos[i].fY;                     
					printf("测温区域2坐标点: X%d:%f,Y%d:%f;\n", iPointNum + 1, fX, iPointNum + 1, fY);                 
				}          
			}

			break;         
		}             
		default:
		{          
			printf("其他报警，报警信息类型: %d\n", lCommand);             
			break;
		}  
	}//switch   
	return TRUE; 
}
#endif

//img char buff
BOOL CALLBACK MessageCallback3_v2(LONG lCommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen, void* pUser) 
{
	// NET_DVR_JPEGPARA strPicPara = {0};
	// strPicPara.wPicQuality = 0;	//图片质量系数：0-最好，1-较好，2-一般 
	// strPicPara.wPicSize = 500;	//500-384*288
	//printf("debug:  thermalcam.cpp::  MessageCallback3()\n");

	switch(lCommand)      
	{                
		case COMM_THERMOMETRY_ALARM: //温度预警或者温度报警         
		{
			//printf("温度预警或者温度报警 : \n");    
			NET_DVR_THERMOMETRY_ALARM struThermometryAlarm = {0};             
			memcpy(&struThermometryAlarm, pAlarmInfo, sizeof(NET_DVR_THERMOMETRY_ALARM));             
			if (0 == struThermometryAlarm.byRuleCalibType)             
			{                 
				printf("点测温: \n"); 
			}             
			else if (1 == struThermometryAlarm.byRuleCalibType || 2 == struThermometryAlarm.byRuleCalibType)             
			{
				char* imgChar = struThermometryAlarm.pThermalPicBuff;
				const int imgLen = struThermometryAlarm.dwThermalPicLen;
				const float fx = struThermometryAlarm.struHighestPoint.fX;
				const float fy = struThermometryAlarm.struHighestPoint.fY;
				const float maxTemp = struThermometryAlarm.fCurrTemperature;
				DEBUG_INFO("max temp: %f, imgBuff size: %d\n", maxTemp, imgLen);
				
				//PRINTINFO("send imgbuf size: %d\n", imgLen);
				const string jsonStr = CLIENTTOSERVICE->m_createJson_alarm(imgLen, struThermometryAlarm.struHighestPoint.fX
																				, struThermometryAlarm.struHighestPoint.fY);
				//PRINTINFO("json: %s\n", jsonStr.c_str());
				
				const int buffSize = imgLen + jsonStr.size();
				
#if 1
				memset(CLIENTTOSERVICE->mp_jsonAndImgBuff, 0, CLIENTTOSERVICE->m_jsonAndImgBuffSize);
				memcpy(CLIENTTOSERVICE->mp_jsonAndImgBuff, jsonStr.c_str(), jsonStr.size() );
				memcpy(CLIENTTOSERVICE->mp_jsonAndImgBuff + jsonStr.size(), imgChar, imgLen);

				// const string imgcheck = "imgcheck";
				// memcpy(CLIENTTOSERVICE->mp_jsonAndImgBuff + jsonStr.size()+imgLen , imgcheck.c_str(), imgcheck.size());
				// const int len = CLIENTTOSERVICE->m_sendBuff2Service(CLIENTTOSERVICE->mp_jsonAndImgBuff, jsonStr.size() + imgLen + 8);
				
				const int len = CLIENTTOSERVICE->m_sendBuff2Service(CLIENTTOSERVICE->mp_jsonAndImgBuff, jsonStr.size() + imgLen);
				if(len == -1){
					WARNING("send info for service error\n");
				}	
				
#else	//run sucess
				const string imgStr(imgChar, imgChar+imgLen);
				const string sendStr = jsonStr + imgStr;
				const int len = CLIENTTOSERVICE->m_sendStr2service(sendStr);
				
				if(len == -1){
					WARNING("send info for service error\n");
				}	
				writeFileIntoLocal(imgChar, imgLen, "/home/ljl/myprograms/thermal-hik/bin/img.jpg");
#endif

				// FILE *fp = NULL;
				// fp = fopen("img.jpg", "wb");
				// fwrite(imgChar, imgLen, 1, fp);
				// fclose(fp);

			}
			break;         
		} //case            
		case COMM_THERMOMETRY_DIFF_ALARM: //温差报警         
		{
			printf("温差报警 : \n");    
			NET_DVR_THERMOMETRY_DIFF_ALARM struThermometryDiffAlarm = {0};             
			memcpy(&struThermometryDiffAlarm, pAlarmInfo, sizeof(NET_DVR_THERMOMETRY_DIFF_ALARM));  
          
			if (0 == struThermometryDiffAlarm.byRuleCalibType)             
			{
				printf("点测温: \n");   
				      
			}             
			else if (1 == struThermometryDiffAlarm.byRuleCalibType || 2 == struThermometryDiffAlarm.byRuleCalibType)             
			{
				printf("线测温或者框测温 : \n");          
				int i = 0;                 
				int iPointNum = struThermometryDiffAlarm.struRegion[0].dwPointNum;                 
				for (i = 0; i < iPointNum; i++)                 
				{                     
					float fX = struThermometryDiffAlarm.struRegion[0].struPos[i].fX;                     
					float fY = struThermometryDiffAlarm.struRegion[0].struPos[i].fY;                     
					printf("测温区域1坐标点: X%d:%f,Y%d:%f;\n", iPointNum + 1, fX, iPointNum + 1, fY);                 
				}                 
				iPointNum = struThermometryDiffAlarm.struRegion[1].dwPointNum;                 
				for (i = 0; i < iPointNum; i++)                 
				{                     
					float fX = struThermometryDiffAlarm.struRegion[1].struPos[i].fX;                     
					float fY = struThermometryDiffAlarm.struRegion[1].struPos[i].fY;                     
					printf("测温区域2坐标点: X%d:%f,Y%d:%f;\n", iPointNum + 1, fX, iPointNum + 1, fY);                 
				}          
			}

			break;         
		}             
		default:
		{          
			printf("其他报警，报警信息类型: %d\n", lCommand);             
			break;
		}  
	}//switch   
	return TRUE; 
}

//设置报警回调函数  
int thermal::AlarmDetect(const int lUserId)
{
 	//set alarm callback function
 	//设置报警回调函数     
    NET_DVR_SetDVRMessageCallBack_V31(MessageCallback3, NULL);
    //启用布防     
    NET_DVR_SETUPALARM_PARAM  struAlarmParam={0};     
    struAlarmParam.dwSize=sizeof(struAlarmParam);     
    //温度或者温差报警不需要设置其他报警布防参数，不支持      
    mLHandle_alarm = NET_DVR_SetupAlarmChan_V41(lUserId, & struAlarmParam);     
    if (mLHandle_alarm < 0)     {         
        printf("NET_DVR_SetupAlarmChan_V41 error, %d\n", NET_DVR_GetLastError());           
        return -1;     
    }
	else{
		printf("\033[1;32mNET_DVR_SetupAlarmChan_V41 success, %d\033[0m\n", mLHandle_alarm);    
	}
	return 0;
}
//send imgBuff to service
int thermal::AlarmDetect_v2(const int lUserId)
{
 	//set alarm callback function
 	//设置报警回调函数     
    NET_DVR_SetDVRMessageCallBack_V31(MessageCallback3_v2, NULL);
    //启用布防     
    NET_DVR_SETUPALARM_PARAM  struAlarmParam={0};     
    struAlarmParam.dwSize=sizeof(struAlarmParam);     
    //温度或者温差报警不需要设置其他报警布防参数，不支持      
    mLHandle_alarm = NET_DVR_SetupAlarmChan_V41(lUserId, & struAlarmParam);     
    if (mLHandle_alarm < 0)     {         
        printf("NET_DVR_SetupAlarmChan_V41 error, %d\n", NET_DVR_GetLastError());           
        return -1;     
    }
	else{
		printf("\033[1;32mNET_DVR_SetupAlarmChan_V41 success, %d\033[0m\n", mLHandle_alarm);    
	}
	return 0;
}
int thermal::closeAlarmDetect(const int lHandle_alarm)
{
	//撤销布防上传通道
	if(lHandle_alarm == -1 ){
		printf("LHandle_alarm == -1\n");
	}
	else if (!NET_DVR_CloseAlarmChan_V30(lHandle_alarm)){
		printf("NET_DVR_CloseAlarmChan_V30 failed, error, %d\n", NET_DVR_GetLastError());
		return -1;
	}

	return 0;
}

int thermal::RealTempDetect(const int lUserId)
{
	//启动实时温度检测
	NET_DVR_REALTIME_THERMOMETRY_COND struThermCond = { 0 };

	struThermCond.dwSize = sizeof(struThermCond);
	struThermCond.byRuleID = m_rule;       //规则ID，0代表获取全部规则，具体规则ID从1开始
	struThermCond.dwChan = dwChannel; 	  //从1开始，0xffffffff代表获取全部通道
	struThermCond.byMode = 1;			//长连接模式：0- 保留（兼容不支持该功能的老设备），1- 定时模式，2-  温差模式
	struThermCond.wInterval = 2;		//send /2s

	/*
	1-定时模式：设备每隔一秒上传各个规则测温数据的最高温、最低温和平均温度值、温差。
	2-温差模式：若上一秒与下一秒的最高温或者最低温或者平均温或者温差值的温差大于等于2摄氏度，
				则上传最高温、最低温和平均温度值；若大于等于一个小时温差值均小于2摄氏度，则上传最高温、最低温、平均温和温差值  
	*/
	mLHandle_realtemp = NET_DVR_StartRemoteConfig(lUserId, NET_DVR_GET_REALTIME_THERMOMETRY, &struThermCond, sizeof(struThermCond), GetThermInfoCallback, this);
	if (mLHandle_realtemp < 0)
	{
		printf("NET_DVR_GET_REALTIME_THERMOMETRY failed, error code: %d lHandle: %d\n", NET_DVR_GetLastError(), mLHandle_realtemp);
		return -1;
	}
	else
	{
		printf("\033[1;32mNET_DVR_GET_REALTIME_THERMOMETRY success! lHandle: %d\033[0m\n", mLHandle_realtemp);
	}
    sleep(0.1);
	return 0;
}


void CALLBACK GetThermInfoCallback(DWORD dwType, void* lpBuffer, DWORD dwBufLen, void* pUserData) 
{   

	if (dwType == NET_SDK_CALLBACK_TYPE_DATA)     
	{         
		LPNET_DVR_THERMOMETRY_UPLOAD lpThermometry = new NET_DVR_THERMOMETRY_UPLOAD;         
		memcpy(lpThermometry, lpBuffer, sizeof(*lpThermometry));


		if(lpThermometry->byRuleCalibType == 0) //点测温         
		{             
			printf("点测温信息:fTemperature[%f]\n", lpThermometry->struPointThermCfg.fTemperature);  
			printf("debug:  thermalcam.cpp::  isCapPicture ###4\n");
		}


		if((lpThermometry->byRuleCalibType==1)||(lpThermometry->byRuleCalibType==2)) //框/线测温         
		{

			const string ftpSendImgPath = regularCapPictureAndFtpSend(LUserID, dwChannel, alarmPath_local, ftpTempPath_thermal_service);
			if(ftpSendImgPath != "null"){
				mutexTempInfo.lock();
				max_thermalTemp = lpThermometry->struLinePolygonThermCfg.fMaxTemperature;
				min_thermalTemp = lpThermometry->struLinePolygonThermCfg.fMinTemperature;
				avg_thermalTemp = lpThermometry->struLinePolygonThermCfg.fAverageTemperature;
				diff_thermalTemp = lpThermometry->struLinePolygonThermCfg.fTemperatureDiff;
				
				isCapPicture = true;
				thermalImagePath_ftp = ftpSendImgPath;
				mutexTempInfo.unlock(); 
				
			}
  
		}               
		if (lpThermometry != NULL)         
		{             
			delete lpThermometry;             
			lpThermometry = NULL;         
		}     

	}   //if
	else if (dwType == NET_SDK_CALLBACK_TYPE_STATUS)     
	{    

		DWORD dwStatus = *(DWORD*)lpBuffer;         
		if (dwStatus == NET_SDK_CALLBACK_STATUS_SUCCESS)         
		{             
			printf("dwStatus:NET_SDK_CALLBACK_STATUS_SUCCESS\n");                     
		}         
		else if (dwStatus == NET_SDK_CALLBACK_STATUS_FAILED)         
		{             
			DWORD dwErrCode = *(DWORD*)((char *)lpBuffer + 4);             
			printf("NET_DVR_GET_MANUALTHERM_INFO failed, Error code %d\n", dwErrCode);         
		}     
	} 

} 

//real temp info and send img
void CALLBACK GetThermInfoCallback_v2(DWORD dwType, void* lpBuffer, DWORD dwBufLen, void* pUserData) 
{  
	if (dwType == NET_SDK_CALLBACK_TYPE_DATA)     
	{         
		LPNET_DVR_THERMOMETRY_UPLOAD lpThermometry = new NET_DVR_THERMOMETRY_UPLOAD;         
		memcpy(lpThermometry, lpBuffer, sizeof(*lpThermometry));

		if(lpThermometry->byRuleCalibType == 0) //点测温         
		{             
			printf("点测温信息:fTemperature[%f]\n", lpThermometry->struPointThermCfg.fTemperature);  
			printf("debug:  thermalcam.cpp::  isCapPicture ###4\n");
		}

		if((lpThermometry->byRuleCalibType==1)||(lpThermometry->byRuleCalibType==2)) //框/线测温         
		{
			SendTempImgcond++;
			SendTempImgcond %= 1000;
			
			if(SendTempImgcond % SendTempImgInterval == 0){
				if(B_sendRealTempImg){	//send json-img
					const string imgPath = alarmPath_local + "/" + getImageName(".jpg");
					if ( capPicture(LUserID, dwChannel, imgPath) == 0){
						
						ifstream is(imgPath.c_str(), ifstream::in | ios::binary);
						is.seekg(0, is.end);
						const int imgLen = is.tellg();
						is.seekg(0, is.beg);

						char imgBuff[imgLen];
						is.read(imgBuff, imgLen);
						is.close();

						deleteFile(imgPath);

						const string jsonStr = CLIENTTOSERVICE->m_createJson_deviceInfo(lpThermometry->struLinePolygonThermCfg.fMaxTemperature, 
																				lpThermometry->struLinePolygonThermCfg.fMinTemperature, 
																				lpThermometry->struLinePolygonThermCfg.fAverageTemperature, 
																				lpThermometry->struLinePolygonThermCfg.fTemperatureDiff
																				, 0
																				, getLocalTime_self_thermal(), imgLen);
						const int jsonStr_len = jsonStr.size();
				
						char sendBuff[jsonStr_len + imgLen];
						memset(sendBuff, 0, jsonStr_len + imgLen);
						memcpy(sendBuff, jsonStr.c_str(), jsonStr_len);
						memcpy(sendBuff + jsonStr_len, imgBuff, imgLen);
						const int len = CLIENTTOSERVICE->m_sendBuff2Service(sendBuff, jsonStr_len + imgLen);
						if(len == -1){
							WARNING("send info for service error\n");
						}	
						else{
							DEBUG_INFO("real thermal info: %s\n", jsonStr.c_str());
						}
					}
					else{
						WARNING("capPicure error\n");
					}

				}
				else{	//send json
					//printf("debug thermalcam.cpp********%d******max temp: %f\n",SendTempImgInterval, lpThermometry->struLinePolygonThermCfg.fMaxTemperature);
					const string jsonStr = CLIENTTOSERVICE->m_createJson_deviceInfo(lpThermometry->struLinePolygonThermCfg.fMaxTemperature, 
																			lpThermometry->struLinePolygonThermCfg.fMinTemperature, 
																			lpThermometry->struLinePolygonThermCfg.fAverageTemperature, 
																			lpThermometry->struLinePolygonThermCfg.fTemperatureDiff
																			, 0
																			, getLocalTime_self_thermal(), 0);
					const int jsonStr_len = jsonStr.size();
			
					const int len = CLIENTTOSERVICE->m_sendBuff2Service(jsonStr.c_str(), jsonStr_len);
					if(len == -1){
						WARNING("send info for service error\n");
					}	
					else{
						DEBUG_INFO("real thermal info: %s\n", jsonStr.c_str());
					}
				}//else
			}//if

			// FILE *fp = NULL;
			// string imgpath = "/home/ljl/Pictures/" + getLocalTime_self() + ".jpg";
			// fp = fopen(const_cast<char*>(imgpath.c_str() ), "wb");
			// fwrite(imgBuff, imgLen, 1, fp);
			// fclose(fp);
			

			//(imgBuff, imgLen, "/home/ljl/Pictures/" + getLocalTime_self() + ".jpg");

			// char sendBuff[jsonStr_len + imgLen];
			// memset(sendBuff, 0, jsonStr_len + imgLen);
			// memcpy(sendBuff, jsonStr.c_str(), jsonStr_len);
			// memcpy(sendBuff + jsonStr_len, imgBuff, imgLen);
			// const int len = CLIENTTOSERVICE->m_sendBuff2Service(sendBuff, jsonStr_len + imgLen);
			
			// if(len == -1){
			// 	WARNING("send info for service error\n");
			// }	
  
		}  //if             
		if (lpThermometry != NULL)         
		{             
			delete lpThermometry;             
			lpThermometry = NULL;         
		}     

	}   //if
	else if (dwType == NET_SDK_CALLBACK_TYPE_STATUS)     
	{    

		DWORD dwStatus = *(DWORD*)lpBuffer;         
		if (dwStatus == NET_SDK_CALLBACK_STATUS_SUCCESS)         
		{             
			printf("dwStatus:NET_SDK_CALLBACK_STATUS_SUCCESS\n");                     
		}         
		else if (dwStatus == NET_SDK_CALLBACK_STATUS_FAILED)         
		{             
			DWORD dwErrCode = *(DWORD*)((char *)lpBuffer + 4);             
			printf("NET_DVR_GET_MANUALTHERM_INFO failed, Error code %d\n", dwErrCode);         
		}     
	} 

} 


//only real temp info
void CALLBACK GetThermInfoCallback_v3(DWORD dwType, void* lpBuffer, DWORD dwBufLen, void* pUserData) 
{   

	if (dwType == NET_SDK_CALLBACK_TYPE_DATA)     
	{         
		LPNET_DVR_THERMOMETRY_UPLOAD lpThermometry = new NET_DVR_THERMOMETRY_UPLOAD;         
		memcpy(lpThermometry, lpBuffer, sizeof(*lpThermometry));


		if(lpThermometry->byRuleCalibType == 0) //点测温         
		{             
			printf("点测温信息:fTemperature[%f]\n", lpThermometry->struPointThermCfg.fTemperature);  
			printf("debug:  thermalcam.cpp::  isCapPicture ###4\n");
		}


		if((lpThermometry->byRuleCalibType==1)||(lpThermometry->byRuleCalibType==2)) //框/线测温         
		{
			const string jsonStr = CLIENTTOSERVICE->m_createJson_deviceInfo(lpThermometry->struLinePolygonThermCfg.fMaxTemperature, 
																	lpThermometry->struLinePolygonThermCfg.fMinTemperature, 
																	lpThermometry->struLinePolygonThermCfg.fAverageTemperature, 
																	lpThermometry->struLinePolygonThermCfg.fTemperatureDiff
																	, 0
																	, getLocalTime_self_thermal(), 0);
			const int jsonStr_len = jsonStr.size();
	
			const int len = CLIENTTOSERVICE->m_sendBuff2Service(jsonStr.c_str(), jsonStr_len);
			if(len == -1){
				WARNING("send info for service error\n");
			}		
		}               
		if (lpThermometry != NULL)         
		{             
			delete lpThermometry;             
			lpThermometry = NULL;         
		}     

	}   //if
	else if (dwType == NET_SDK_CALLBACK_TYPE_STATUS)     
	{    

		DWORD dwStatus = *(DWORD*)lpBuffer;         
		if (dwStatus == NET_SDK_CALLBACK_STATUS_SUCCESS)         
		{             
			printf("dwStatus:NET_SDK_CALLBACK_STATUS_SUCCESS\n");                     
		}         
		else if (dwStatus == NET_SDK_CALLBACK_STATUS_FAILED)         
		{             
			DWORD dwErrCode = *(DWORD*)((char *)lpBuffer + 4);             
			printf("NET_DVR_GET_MANUALTHERM_INFO failed, Error code %d\n", dwErrCode);         
		}     
	} 

} 

int thermal::RealTempDetect_v2(const int lUserId)
{
	//启动实时温度检测
	NET_DVR_REALTIME_THERMOMETRY_COND struThermCond = { 0 };

	struThermCond.dwSize = sizeof(struThermCond);
	struThermCond.byRuleID = m_rule;       //规则ID，0代表获取全部规则，具体规则ID从1开始
	struThermCond.dwChan = dwChannel; 	  //从1开始，0xffffffff代表获取全部通道
	struThermCond.byMode = 1;			//长连接模式：0- 保留（兼容不支持该功能的老设备），1- 定时模式，2-  温差模式
	struThermCond.wInterval = m_realtemp_interval;		//send /2s  only work for 温差模式

	/*
	1-定时模式：设备每隔一秒上传各个规则测温数据的最高温、最低温和平均温度值、温差。
	2-温差模式：若上一秒与下一秒的最高温或者最低温或者平均温或者温差值的温差大于等于2摄氏度，
				则上传最高温、最低温和平均温度值；若大于等于一个小时温差值均小于2摄氏度，则上传最高温、最低温、平均温和温差值  
	*/
	mLHandle_realtemp = NET_DVR_StartRemoteConfig(lUserId, NET_DVR_GET_REALTIME_THERMOMETRY, &struThermCond, sizeof(struThermCond), GetThermInfoCallback_v2, this);
	if (mLHandle_realtemp < 0)
	{
		printf("NET_DVR_GET_REALTIME_THERMOMETRY failed, error code: %d lHandle: %d\n", NET_DVR_GetLastError(), mLHandle_realtemp);
//debug	
		return -1;
	}
	else
	{
		printf("\033[1;32mNET_DVR_GET_REALTIME_THERMOMETRY success! lHandle: %d\033[0m\n", mLHandle_realtemp);
	}
    sleep(0.1);
	return 0;
}

int thermal::closeRealTempDetect(const int lHandle_realtemp)
{
	//关闭长连接配置接口所创建的句柄，释放资源  LHandle_alarm
	if (lHandle_realtemp != -1 && !NET_DVR_StopRemoteConfig(lHandle_realtemp))
	{
		printf("NET_DVR_StopRemoteConfig failed, error code: %d\n", NET_DVR_GetLastError());
		return -1;
	}

	return 0;
}


void pushAlarm(const string &strImgPath, const string &strImg, const float point_x, const float point_y)
{
	std::unique_lock<std::mutex> lock(mutexTempAlarm);		//automatically calls lock on mtx
	isTempAlarm = true;
	//strncpy(TempAlarmImagePath, strImgPath.c_str(), strImgPath.length() + 1); // 注意，一定要加1，否则没有赋值'\0'
	TempAlarmImagePath = strImgPath;
	highPositionFx = point_x;
	highPositionFy = point_y;
	//alarmImage = matImg.clone();
}
void setThermalTempInfo(const float max, const float min, const float avg, const float diff, const string ftpSendImgPath)
{
	std::unique_lock<std::mutex> lock(mutexTempInfo);
	max_thermalTemp = max;
	min_thermalTemp = min;
	avg_thermalTemp = avg;
	diff_thermalTemp = diff;

	isCapPicture = true;
	thermalImagePath_ftp = ftpSendImgPath;
}
void getThermalTempInfo(float &max, float &min, float &avg, float &diff, string &ftpSendImgPath)
{
	std::unique_lock<std::mutex> lock(mutexTempInfo);
	max = max_thermalTemp;
	min = min_thermalTemp;
	avg = avg_thermalTemp;
	diff = diff_thermalTemp;

	isCapPicture = false;
	ftpSendImgPath = thermalImagePath_ftp;
}



//           /home/user/ljl/catkin_tcp/socket_part/bin/xxx
// when N=2, /home/user/ljl/catkin_tcp/socket_part/
// when N=3, /home/user/ljl/catkin_tcp/
int thermal_get_exe_path(string &fpath, int N) 
{
    char link[100];
    char path[100];
    sprintf(link, "/proc/%d/exe", getpid() );
    int num = readlink(link, path, sizeof(path) );
    if (num < 0 || num >= 100 || N > num){
        printf("**Error**\n");
        printf("num: %d,  N: %d\n", num, N);
        exit(-1);
    }

    int cnt = 0;
    for (int i=num-1; i>=0; i--){
        if (path[i] == '/' || path[i] == '\\'){
            cnt++;
            if(cnt == N){
                path[i+1] = '\0';
                break;
            }
        }
    }
    fpath = path;
	return 0;
}


void thermal::SDK_Version()
{
    unsigned int uiVersion = NET_DVR_GetSDKBuildVersion();

    char strTemp[1024] = {0};
    sprintf(strTemp, "HCNetSDK V%d.%d.%d.%d\n", \
        (0xff000000 & uiVersion)>>24, \
        (0x00ff0000 & uiVersion)>>16, \
        (0x0000ff00 & uiVersion)>>8, \
        (0x000000ff & uiVersion));
    printf("%s", strTemp);
}

/*
设备工作状态信息结构体。
Members
    dwDeviceStatic  设备的状态：0－正常；1－CPU占用率太高，超过85%；2－硬件错误，例如串口异常  
    struHardDiskStatic  硬盘状态  
    struChanStatic  通道状态  
    byAlarmInStatic  报警输入口的状态：0-没有报警；1-有报警  
    byAlarmOutStatic  报警输出口的状态：0-没有输出，1-有报警输出  
    dwLocalDisplay  本地显示状态：0-正常，1-不正常  
    byAudioChanStatus  表示语音通道的状态：0-未使用，1-使用中，0xff无效  
    byRes  保留，置为0 

*/
//Get device state
int Demo_GetDeviceState(LONG lUserID)
{
    printf("设备工作状态信息:\n");
    NET_DVR_WORKSTATE_V30    struWorkState;
    if (NET_DVR_GetDVRWorkState_V30(lUserID, &struWorkState))
    {
        printf("pyd---NET_DVR_GetDVRWorkState_V30 success.\n");
    } 
    else
    {
        printf("pyd---NET_DVR_GetDVRWorkState_V30 error, %d.\n", NET_DVR_GetLastError());
        return HPR_ERROR;
    }

    printf("  设备的状态：0－正常；1－CPU占用率太高, 2－硬件错误，例如串口异常 -> %d\n", struWorkState.dwDeviceStatic);
    //printf("硬盘状态:%d\n", struWorkState.struHardDiskStatic);
    //printf("通道状态:%d\n", struWorkState.struChanStatic);
    printf("  报警输入口的状态：0-没有报警；1-有报警 -> %d\n", *struWorkState.byAlarmInStatic);
    printf("  报警输出口的状态：0-没有输出，1-有报警输出 -> %d\n", *struWorkState.byAlarmOutStatic);
    printf("  本地显示状态：0-正常，1-不正常 -> %d\n", struWorkState.dwLocalDisplay);
    printf("  语音通道的状态：0-未使用，1-使用中，0xff无效 -> %d\n", *struWorkState.byAudioChanStatus);
    return HPR_OK;
}

//imgpath:  src source
int sendftp(const string FTPServer, const string imgpath, const string uploadDirectory, const string ftpUser, const string ftopassword, const string shName)
{       

    char FTPPort[20] = "21";
	string ShScript = shName;				//"./thermal_normal.sh" ;
	FILE *file = fopen(ShScript.c_str(), "w");
	if (file)
	{
	// 参数说明详见第一部分
		fprintf(file, "#!/bin/bash\n"				
			"ncftpput " "-u %s " "-p %s " "-P %s " " %s " 
			" %s %s >/dev/null 2&>/dev/null\n"
			"path=%s\n"
			// "if [ -f \"$path\" ];then\n"
			// "	sleep 0.1"
			// "	rm $path\n"
			// "fi\n"
			"!\n"
			"exit",
			// 前后加！的作用类似C中的{}，此处的作用是禁止交互和表面shell回显信息
			ftpUser.c_str(), ftopassword.c_str(), FTPPort, FTPServer.c_str(), 
			uploadDirectory.c_str(), imgpath.c_str(), imgpath.c_str()
			);
		fclose(file);
		chmod(ShScript.c_str(), 0755);
		//ShScript += "&";
		// 通过system函数执行脚本
		system(ShScript.c_str());

		if(access(imgpath.c_str(), F_OK) == 0){
			const string rmImg = "rm " + imgpath;
			system(rmImg.c_str());
		}
	}
	else
	{
		printf("[Error] create shell script .bat:  %s failed!\n", ShScript.c_str());
		return -1;
	}
	return 0;
}

//transform " " of time into "_"
//imgType: ".jpg"
string getImageName(const string imgType)
{
	string localTime = getLocalTime_self_thermal();
	const int idx = localTime.find(" ");
	const int len = localTime.size();
	localTime = localTime.substr(0,idx) + "_" + localTime.substr(idx+1, len-1-idx) + imgType.c_str();

	return localTime;
}

//get current run date
string getcurrentDate()
{
	//get current run date
    char date[50];
    memset(date, 0, sizeof(date));
    getLocalTime_self_thermal(date);
    string currentDate = date;
    const int idx_date = currentDate.find(" ");
    return currentDate.substr(0, idx_date);

}

Json::Value thermalCamera_tempInfoBeatInit(const string id)
{
    std::string jsonStr;
    Json::Value  TunnelTemperature , root;
    Json::StreamWriterBuilder writerBuilder;
    std::ostringstream os;

    TunnelTemperature["ID"] = id;
    TunnelTemperature["Maximum"] = 0;
    TunnelTemperature["Minimal"] = 0;
    TunnelTemperature["Average"] = 0;
    TunnelTemperature["CurrentPosition"] = 0;
    TunnelTemperature["CurrentTime"] = "2017-12-14 09:30:23";

    root["TunnelTemperature"] = Json::Value(TunnelTemperature);
    return root;
}



int thermal::getThermMode(const int lUserID)
{
	//get 测温Mode配置
    NET_DVR_STD_CONFIG struStdConfig = { 0 };

	NET_DVR_THERMOMETRY_MODE struThermMode = { 0 };
    struStdConfig.lpCondBuffer = &dwChannel;
	struStdConfig.dwCondSize = sizeof(dwChannel);
	struStdConfig.lpInBuffer = NULL;
	struStdConfig.dwInSize = 0;
	
	struStdConfig.lpOutBuffer = &struThermMode;   //out param
	struStdConfig.dwOutSize = sizeof(struThermMode);

	char  szStatusBuf[ISAPI_STATUS_LEN];
	memset(szStatusBuf, 0, ISAPI_STATUS_LEN);
	struStdConfig.lpStatusBuffer = szStatusBuf;      //out param
    struStdConfig.dwStatusSize = ISAPI_STATUS_LEN;
	//get TemplateModes
	int iRet = NET_DVR_GetSTDConfig(lUserID, NET_DVR_GET_THERMOMETRY_MODE, &struStdConfig);
	if (!iRet)	
	{
		printf("NET_DVR_GET_THERMOMETRY_MODE failed, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
        return -1;
	}
	else
	{
		printf("NET_DVR_GET_THERMOMETRY_MODE success! iRet: %d  ", iRet);
		printf ("MODE:  %d, 0 : normal\n", struThermMode.byMode);	//0 : normal
		
	}
	return 0;
}

int thermal::setThermParams(const int lUserID)
{
	printf("setParams: \n");
	int iRet;

	//set system params
	iRet = setThermParams_sys(lUserID);
	if(iRet == -1){
		return -1;
	}
	iRet = setThermParams_basicParam(lUserID);
	if(iRet == -1){
		printf("setThermParams_basicParam() error\n");
		// return -1;
	}

	return 0;
}

//strucPiccFG.byOSDType = 0   year-month-day          //0-8
int thermal::setThermParams_sys(const int lUserID){
	//get system params
	DWORD len;	//out param
	NET_DVR_PICCFG_V40 strucPiccFG = { 0 };		// out param
	int iRet = NET_DVR_GetDVRConfig(lUserID, NET_DVR_GET_PICCFG_V40, dwChannel, &strucPiccFG, sizeof(strucPiccFG), &len);
	if (!iRet)
	{
		printf("	NET_DVR_GET_PICCFG_V40 failed, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
        return -1;
	}
	else
	{
		printf("	NET_DVR_GET_PICCFG_V40 success! iRet: %d\n", iRet);
	}
	//set system params
	const string robotName = m_selfName;
	strncpy((char*)strucPiccFG.sChanName, robotName.c_str(), robotName.length()+1 );
	strucPiccFG.byOSDType = m_byOSDType;			//year-month-day
	strucPiccFG.byDispWeek = m_byDispWeek;
	

	iRet = NET_DVR_SetDVRConfig(lUserID, NET_DVR_SET_PICCFG_V40, dwChannel, &strucPiccFG, sizeof(strucPiccFG));
	if (!iRet)
	{
		printf("	NET_DVR_SET_PICCFG_V40 failed, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
        return -1;
	}
	else
	{
		printf("	NET_DVR_SET_PICCFG_V40 success! iRet: %d\n", iRet);
		printf("	strucPiccFG.sChanName: %s\n", strucPiccFG.sChanName);
		printf("	strucPiccFG.dwShowOsd: %d\n", strucPiccFG.dwShowOsd);
		printf("	strucPiccFG.byOSDType: %d\n", strucPiccFG.byOSDType);
		printf("	strucPiccFG.byDispWeek: %d\n", strucPiccFG.byDispWeek);
	}
	printf("	***\n");
	printf("	image param set success\n");
	printf("	***\n");
	//<<<
	return 0;
}


int thermal::setThermParams_basicParam(const int lUserID)
{
	NET_DVR_STD_CONFIG struStdConfig = { 0 };
	char  szStatusBuf[ISAPI_STATUS_LEN];
	//get 测温基本参数配置
	NET_DVR_THERMOMETRY_BASICPARAM struThermometryBasic = { 0 };
    struStdConfig.lpCondBuffer = &dwChannel;
	struStdConfig.dwCondSize = sizeof(dwChannel);
	struStdConfig.lpInBuffer = NULL;
	struStdConfig.dwInSize = 0;
	
	struStdConfig.lpOutBuffer = &struThermometryBasic;   //out param
	struStdConfig.dwOutSize = sizeof(struThermometryBasic);

	memset(szStatusBuf, 0, ISAPI_STATUS_LEN);
	struStdConfig.lpStatusBuffer = szStatusBuf;      //out param
    struStdConfig.dwStatusSize = ISAPI_STATUS_LEN;
	int iRet = NET_DVR_GetSTDConfig(lUserID, NET_DVR_GET_THERMOMETRY_BASICPARAM, &struStdConfig);
	if (!iRet)	
	{
		printf("	NET_DVR_GET_THERMOMETRY_BASICPARAM failed, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
        return -1;
	}
	else
	{
		printf("	NET_DVR_GET_THERMOMETRY_BASICPARAM success! iRet: %d\n", iRet);
	}
	//set 测温基本参数配置
	{

    // struThermometryBasic.byEnabled = m_bEnbaleThermometry;
    // struThermometryBasic.byStreamOverlay = m_bStreamOverlay;
    // struThermometryBasic.byPictureOverlay = m_bPictureOverlay;
    // struThermometryBasic.byThermometryRange = 1; //测温范围（这里以摄氏度为单位计算，其他单位由上层自行转换）：0- 默认值，1- (-20~150)，2- (0~550)  0xff :auto
	// struThermometryBasic.byemissivityMode = 0xff; //发射率配置类型： 1- 粗糙(0.95)，2- 较粗糙(0.80)，3- 较光滑(0.60)，4- 光滑(0.30)，0xff-  自定义(0.01-1.00)  
	// struThermometryBasic.byThermometryUnit = m_byThermometryUnit;  //测温单位（所有测温配置功能中温度参数对应的单位）: 0- 摄氏度（℃），1- 华氏度（℉），2- 开尔文(K) 
    // struThermometryBasic.struTempColor.byType = m_comTemperatureColor;
    // struThermometryBasic.struTempColor.iHighTemperature = m_iHighTemperature;
    // struThermometryBasic.struTempColor.iLowTemperature = m_iLowTemperature;
    

    // struThermometryBasic.byFireImageModea = m_cmbFireImageModea;
    // struThermometryBasic.byThermometryCurve = m_cmbThermometryCurve;
    // struThermometryBasic.fEmissivity = m_fThernomertryEmissivity;		//发射率(发射率 精确到小数点后两位)[0.01, 1.00](即：物体向外辐射能量的本领)
	// struThermometryBasic.byDistanceUnit = m_comDistanceUnit;					//距离单位: 0- 米(m)，1- 英尺(feet)，2-厘米（cm） 
    // struThermometryBasic.byEnviroHumidity = m_byEnviroHumidity;
    // struThermometryBasic.iEnviroTemperature = m_iEnviroTemperature;		//-273~10000 
    // struThermometryBasic.iCorrectionVolume = m_iCorrectionVolume;
    // struThermometryBasic.bySpecialPointThermType = 0;
    // struThermometryBasic.bySpecialPointThermType |= (m_bChkCenterSpecialPoint << 0);
    // struThermometryBasic.bySpecialPointThermType |= (m_bChkHighestSpecialPoint << 1);
    // struThermometryBasic.bySpecialPointThermType |= (m_bChkLowestSpecialPoint << 2);
    // struThermometryBasic.byReflectiveEnabled = m_bChkReflectiveEnabled;
    // struThermometryBasic.wDistance = m_dwDistanceMeter;
    // struThermometryBasic.fReflectiveTemperature = m_fReflectiveTemp;
    // struThermometryBasic.byShowTempStripEnable = m_bShowTempStripEnable;		//显示温度条使能：0- 否，1- 是 

     struThermometryBasic.fAlert = m_fAlertVal;			//***
     struThermometryBasic.fAlarm = m_fAlarmVal;			//***
    // struThermometryBasic.fThermalOpticalTransmittance = m_ThermalOpticalTransmittance;
    // struThermometryBasic.fExternalOpticsWindowCorrection = m_externalOpticsWindowCorrection;
    // struThermometryBasic.byDisplayMaxTemperatureEnabled = m_displayMaxTemperatureEnabled;
    // struThermometryBasic.byDisplayMinTemperatureEnabled = m_displayMinTemperatureEnabled;
    // struThermometryBasic.byDisplayAverageTemperatureEnabled = m_displayAverageTemperatureEnabled;
    // struThermometryBasic.byThermometryInfoDisplayposition = m_thermometryInfoDisplayposition;
    // struThermometryBasic.dwAlertFilteringTime = m_AlertFilteringTime;
    // struThermometryBasic.dwAlarmFilteringTime = m_AlarmFilteringTime;
    // struThermometryBasic.bydisplayTemperatureInOpticalChannelEnabled=m_displayTemperatureInOpticalChannelEnabled;
    // struThermometryBasic.byDisplayCentreTemperatureEnabled = m_displayCentreTemperatureEnabled;
    // struThermometryBasic.dwSize = sizeof(struThermometryBasic);
	}

    struStdConfig.lpCondBuffer = &dwChannel;
    struStdConfig.dwCondSize = sizeof(dwChannel);
    struStdConfig.lpInBuffer = &struThermometryBasic;
    struStdConfig.dwInSize = sizeof(struThermometryBasic);
    memset(szStatusBuf, 0, ISAPI_STATUS_LEN);
    struStdConfig.lpStatusBuffer = szStatusBuf;
    struStdConfig.dwStatusSize = ISAPI_STATUS_LEN;
    
    iRet = NET_DVR_SetSTDConfig(lUserID, NET_DVR_SET_THERMOMETRY_BASICPARAM, &struStdConfig);
    if (!iRet)	
	{

		printf("	NET_DVR_SET_THERMOMETRY_BASICPARAM failed, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
        return -1;
	}
	else
	{	
		printf("	NET_DVR_SET_THERMOMETRY_BASICPARAM success! iRet: %d\n", iRet);
	}

	//get params that have been setted
	NET_DVR_THERMOMETRY_BASICPARAM struThermometryBasicCheckout = { 0 };
    struStdConfig.lpCondBuffer = &dwChannel;
	struStdConfig.dwCondSize = sizeof(dwChannel);
	struStdConfig.lpInBuffer = NULL;
	struStdConfig.dwInSize = 0;
	
	struStdConfig.lpOutBuffer = &struThermometryBasicCheckout;   //out param
	struStdConfig.dwOutSize = sizeof(struThermometryBasicCheckout);

	memset(szStatusBuf, 0, ISAPI_STATUS_LEN);
	struStdConfig.lpStatusBuffer = szStatusBuf;      //out param
    struStdConfig.dwStatusSize = ISAPI_STATUS_LEN;
	iRet = NET_DVR_GetSTDConfig(lUserID, NET_DVR_GET_THERMOMETRY_BASICPARAM, &struStdConfig);
	if (!iRet)	
	{
		printf("	NET_DVR_GET_THERMOMETRY_BASICPARAM failed, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
        return -1;
	}
	else
	{
		printf("	NET_DVR_GET_THERMOMETRY_BASICPARAM success! iRet: %d\n", iRet);
		printf("	thermal camera alarm template: %.2f\n", struThermometryBasicCheckout.fAlarm);
		printf("	thermal camera alert template: %.2f\n", struThermometryBasicCheckout.fAlert);
		
	}
	return 0;
}

int thermal::getAbility_thermal(const int lUserID)
{
	NET_DVR_STD_ABILITY struStdAbility = {0};
	char  outBuf[ISAPI_OUT_LEN];
	memset(outBuf, 0, ISAPI_OUT_LEN);

	char  statusBuf[ISAPI_STATUS_LEN];
	memset(statusBuf, 0, ISAPI_STATUS_LEN);

    struStdAbility.lpCondBuffer = &dwChannel;
	struStdAbility.dwCondSize = sizeof(dwChannel);
	
	struStdAbility.lpOutBuffer = outBuf;   //out param
	struStdAbility.dwOutSize = ISAPI_OUT_LEN;

	struStdAbility.lpStatusBuffer = statusBuf;      //out param
    struStdAbility.dwStatusSize = ISAPI_STATUS_LEN;
	//get abilities
	printf("thermal abilies: \n");
	int iRet = NET_DVR_GetSTDAbility(lUserID, NET_DVR_GET_THERMAL_CAPABILITIES, &struStdAbility);
	if (!iRet)	
	{
		printf("	NET_DVR_GET_THERMAL_CAPABILITIES, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
        return -1;
	}
	else
	{
		printf("	NET_DVR_GET_THERMAL_CAPABILITIES success! iRet: %d  \n", iRet);
	}


	iRet = NET_DVR_GetSTDAbility(lUserID, NET_DVR_GET_TEMP_HUMI_CAPABILITIES, &struStdAbility);
	if (!iRet)	
	{
		printf("	NET_DVR_GET_TEMP_HUMI_CAPABILITIES, error code: %d iRet: %d\n", NET_DVR_GetLastError(), iRet);
        return -1;
	}
	else
	{
		printf("	NET_DVR_GET_TEMP_HUMI_CAPABILITIES success! iRet: %d  \n", iRet);
	}

	return 0;
}

string regularCapPictureAndFtpSend(const int lUserId, const int channel, const string localSaveImg_tempPath, const string ftpImagePath)
{
	//printf("线测温或者框测温: \n");
	const string imgName = getImageName(".jpg");  
	const string filePathName = localSaveImg_tempPath + "/" + imgName;	//save local
	//const string data = getcurrentDate();

	capPicture(lUserId, channel, filePathName.c_str());
	sendftp(IP_service, filePathName, ftpImagePath, "robot001", "robot001", "./thermal_normal.sh");

	return ftpImagePath + "/" + imgName;
}

//add path date
//in: /home/ljl/imagedata  -> out: /home/ljl/imagedata/2021-09-10
int createSaveImgFolder(string folderPath,  string &outFolderPath)
{
        //get current run date
    char date[50];
    memset(date, 0, sizeof(date));
    getLocalTime_self_thermal(date);
    string date_storage_imgProcess = date;
    const int idx_date = date_storage_imgProcess.find(" ");
    date_storage_imgProcess = date_storage_imgProcess.substr(0, idx_date);

    folderPath = folderPath + "/" + date_storage_imgProcess;
    if(access(folderPath.c_str(),  F_OK) != 0){
        const string commandMkdir = "echo ruitu123 | sudo -S mkdir -m 777 -p " + folderPath;
        system(commandMkdir.c_str());
        if ( access(folderPath.c_str(),  F_OK) != 0 ){
            printf("\033[1;31merror:\033[0mdate folder: create folder: mkdir error: %s\n", folderPath.c_str() );
            return -1;
        }
    }
    outFolderPath = folderPath;

    return 0;
}

void writeFileIntoLocal(char *pfile, const unsigned int len, const string path)
{
	FILE *fp = NULL;
	fp = fopen(const_cast<char*>(path.c_str() ), "wb");
	fwrite(pfile, len, 1, fp);
	fclose(fp);
}

void deleteFile(const string filePath)
{

	if(access(filePath.c_str(), F_OK) == 0){
		const string rmImg = "rm " + filePath;
		system(rmImg.c_str());
	}
}







